package registration;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import user.*;

import common.*;
import common.dal.Transaction;
import common.exceptions.*;
import common.interfaces.IPersistent;

@SuppressWarnings({"javadoc"})
public class DBVoteManagerTest extends DBTest {
	private static DBVoteManager	$;
	private Consensus				con;
	
	@Override
	protected IPersistent setPersistent(Transaction t) {
		$ = new DBVoteManager(t);
		return $;
	}
	
	@Override
	protected IPersistent getPersistent() {
		return $;
	}
	
	@Before
	public void setupConsensus() throws Exception {
		con = RegistrationManager.getNewInstance(t).addConsensus(getEvent(), "consensus");
		RegistrationManager.getNewInstance(t).registerUserForEvent(getUser(), getEvent());
	}
	
	@After
	public void tearDownConsensus() throws Exception {
		RegistrationManager.getNewInstance(t).unregisterUserForEvent(getUser(), getEvent());
	}
	
	@Test
	public void testVote() throws Exception {
		assertNull($.getVote(con, getUser()));
		$.vote(con, getUser(), false);
		assertFalse($.getVote(con, getUser()));
		$.vote(con, getUser(), true);
		assertTrue($.getVote(con, getUser()));
		$.vote(con, getUser(), false);
		assertFalse($.getVote(con, getUser()));
	}
	
	@Test(expected = IllegalArgumentException.class)
	public void testUserNotRegistered() throws Exception {
		RegistrationManager.getNewInstance(t).unregisterUserForEvent(getUser(), getEvent());
		$.vote(con, getUser(), false);
	}
	
	@Test(expected = InvalidUserException.class)
	public void testBadUser() throws Exception {
		$.vote(con, getFakeUser(), false);
	}
	
	@Test
	public void testHasConsensusBeenReached() throws Exception {
		RegistrationManager.getNewInstance(t).unregisterUserForEvent(getUser(), getEvent());
		assertNull($.getConsensusStatus(con));
		RegistrationManager.getNewInstance(t).registerUserForEvent(getUser(), getEvent());
		assertNull($.getConsensusStatus(con));
		$.vote(con, getUser(), false);
		assertFalse($.getConsensusStatus(con));
		$.vote(con, getUser(), true);
		assertTrue($.getConsensusStatus(con));
		User tempUser = LoginManager.getNewInstance(t)
				.registerUser("b" + Calendar.getInstance().getTimeInMillis(), "gal2", PASSWORD);
		RegistrationManager.getNewInstance(t).registerUserForEvent(tempUser, getEvent());
		assertNull($.getConsensusStatus(con));
		$.vote(con, tempUser, false);
		assertNull($.getConsensusStatus(con));
		$.vote(con, getUser(), false);
		assertFalse($.getConsensusStatus(con));
	}
	
	@Test
	public void testGetAllVotes() throws Exception {
		RegistrationManager.getNewInstance(t).registerUserForEvent(getUser(), getEvent());
		assertEquals(Collections.emptySet(), new HashSet<>($.getAllVotes(con)));
		assertEquals(Collections.emptySet(), new HashSet<>($.getAllVotes(con)));
		$.vote(con, getUser(), true);
		Set<Pair<User, Boolean>> expected = new HashSet<>();
		expected.add(Pair.of(getUser(), true));
		assertEquals(expected, new HashSet<>($.getAllVotes(con)));
		$.vote(con, getUser(), false);
		expected.clear();
		expected.add(Pair.of(getUser(), false));
		Consensus con2 = RegistrationManager.getNewInstance(t).addConsensus(getEvent(), "new consensus");
		assertEquals(Collections.emptySet(), new HashSet<>($.getAllVotes(con2)));
		$.vote(con2, getUser(), false);
		expected.clear();
		expected.add(Pair.of(getUser(), false));
	}
	
	@Test(expected = InvalidConsensusException.class)
	public void testGetVoteBadCon() throws Exception {
		RegistrationManager.getNewInstance(t).removeConsensus(con.getId());
		$.getVote(con, getUser());
	}
	
	@Test(expected = InvalidUserException.class)
	public void testGetVoteBadUser() throws Exception {
		$.getVote(con, getFakeUser());
	}
	
	@Test(expected = IllegalArgumentException.class)
	public void testGetVoteUserNotRegistered() throws Exception {
		RegistrationManager.getNewInstance(t).unregisterUserForEvent(getUser(), getEvent());
		$.getVote(con, getUser());
	}
	
	@Test
	public void testGetVote() throws Exception {
		assertNull($.getVote(con, getUser()));
		$.vote(con, getUser(), false);
		assertFalse($.getVote(con, getUser()));
		$.vote(con, getUser(), true);
		assertTrue($.getVote(con, getUser()));
	}
	
	@Test
	public void testRemoveAllVotesCon() throws Exception {
		Consensus con2 = RegistrationManager.getNewInstance(t).addConsensus(getEvent(), "name2");
		$.vote(con, getUser(), false);
		$.vote(con2, getUser(), false);
		$.removeAllVotes(con);
		assertEquals(Collections.EMPTY_SET, new HashSet<>($.getAllVotes(con)));
		Set<Object> expected = new HashSet<>();
		expected.add(Pair.of(getUser(), false));
		assertEquals(expected, new HashSet<Object>($.getAllVotes(con2)));
	}
	
	@Test
	public void testRemoveAllVotesUser() throws Exception {
		Consensus con2 = RegistrationManager.getNewInstance(t).addConsensus(getEvent(), "name2");
		$.vote(con, getUser(), false);
		$.vote(con2, getUser(), false);
		$.removeAllVotes(getUser());
		assertEquals(Collections.EMPTY_SET, new HashSet<>($.getAllVotes(con)));
		assertEquals(Collections.EMPTY_SET, new HashSet<Object>($.getAllVotes(con2)));
	}
}
